local modname = minetest.get_current_modname()
local function trans(st,...)
	return minetest.translate(modname,st,...)
end
local function show_formspec(itemstack,pname)
	local formspec = ""
	formspec = formspec.."formspec_version[3]"
	formspec = formspec.."size[10.5,7.5]"

	formspec = formspec.."label[0.2,0.4;"..trans("Advanced Trains Remote Control v1").."]"

	formspec = formspec.."button_exit[6.6,0.2;3.7,0.8;bind_train;"..trans("Bind To New Train").."]"

	local item_meta = itemstack:get_meta()
	local loco_id = item_meta:get("bound_loco")	
	
	if not loco_id then
		formspec = formspec.."label[0.2,1;"..trans("Remote Control: Not Bound").."]"
		formspec = formspec.."label[0.2,1.4;"..trans("Punch a locomotive with the controller to bind it").."]"
	else
		local train_id = advtrains.wagons[loco_id].train_id --ref to train for atc controls etc
		local train = advtrains.trains[train_id] -- train object 
		formspec = formspec.."label[0.2,1;"..trans("Roadnumber")..": %s]"
		formspec = formspec.."label[0.2,1.4;"..trans("Remote Control: Train").." %s]"
		formspec = formspec.."label[0.2,1.8;"..trans("Train Length")..": %s wagon(s)]"
		formspec = formspec.."label[0.2,2.2;"..trans("Train Length")..": %sm]"

		formspec = formspec.."textarea[0.2,2.9;5.8,0.8;ext_disp;"..trans("External Display")..";%s]"
		formspec = formspec.."textarea[0.2,4.1;5.8,0.8;int_disp;"..trans("Internal Display")..";%s]"
		formspec = formspec.."field[0.2,6.5;2.8,0.8;line;"..trans("Line")..";%s]"
		formspec = formspec.."field[0.2,5.3;5.8,0.8;rc;"..trans("Routing Code")..";%s]"
		formspec = formspec.."button[3.2,6.5;2.8,0.8;update_info;"..trans("Update Train Info").."]"

		formspec = formspec.."label[6.6,1.6;"..trans("Maximum Speed")..": %s m/s]"
		formspec = formspec.."field[6.6,2.9;1.9,0.8;speed_input;"..trans("Set Speed")..";%d]"
		formspec = formspec.."button[8.8,2.9;1.5,0.8;send_speed;"..trans("Confirm").."]"
		formspec = formspec.."field[6.6,4.1;1.9,0.8;atc_input;"..trans("Send ATC Command")..";]"
		formspec = formspec.."button[8.8,4.1;1.5,0.8;send_atc;"..trans("Send").."]"
		formspec = formspec.."button[6.6,5.3;3.7,0.8;reverse;"..trans("Reverse").."]"

		formspec = formspec.."label[6.6,2;"..trans("Door Control").."]"
		formspec = formspec.."scrollbaroptions[min=1;max=3;smallstep=1;largestep=1;thumbsize=1;arrows=hide]scrollbar[6.6,2.2;3.7,0.2;horizontal;door;%d]"
		
		formspec = formspec.."checkbox[6.6,6.6;ars_disable;"..trans("Disable ARS")..";%s]"
		formspec = formspec.."checkbox[6.6,7.1;autocouple;"..trans("Autocouple")..";%s]"

		formspec = formspec.."button[9.1,6.5;1.2,0.8;estop;"..trans("STOP!").."]"
	
		formspec = string.format(formspec,
			minetest.formspec_escape(item_meta:get("roadnumber") or trans("Unidentified Locomotive")),
			train_id,
			#train.trainparts,
			train.trainlen,
			minetest.formspec_escape(train.text_outside or ""),
			minetest.formspec_escape(train.text_inside or ""),
			minetest.formspec_escape(train.line or ""),
			minetest.formspec_escape(train.routingcode or ""),
			train.max_speed,
			train.velocity,
			((train.door_open or 0) + 2),
			tostring(train.ars_disable),
			tostring(train.autocouple or train.atc_wait_autocouple)
		)
	end
	minetest.show_formspec(pname,modname..":controller",formspec)
end

minetest.register_on_player_receive_fields(function(player,formname,fields)
	if formname ~= modname..":controller" then return end
	local pname = player:get_player_name()
	if not pname then return end
	local itemstack = player:get_wielded_item()
	if itemstack:get_name() ~= modname..":remote_control" then return end
	
	local item_meta = itemstack:get_meta()
	
	--bind train
	if fields.bind_train then
		item_meta:set_string("bound_loco","")
		item_meta:set_string("roadnumber","")
		item_meta:set_string("description",trans("Unbound Controller"))
		player:set_wielded_item(itemstack)
		minetest.chat_send_player(pname,trans("Punch a locomotive with the controller to bind it"))
		return
	end
	
	local loco_id = item_meta:get("bound_loco")
	if loco_id then
		--[[list of fields:
			active fields:
				bind_train
				update_info
				send_speed
				send_atc
				reverse
				door
				ars_disable
				autocouple
				estop
			data fields:
				ext_disp
				int_disp
				line
				rc
				speed_input
				atc_input
		--]]
		local wagon = advtrains.wagons[loco_id] -- wagon_object for potential use later
		local train_id = wagon.train_id
		local train = advtrains.trains[train_id]
		
		--update info
		local door_scroll = minetest.explode_scrollbar_event(fields.door)
		if fields.update_info then
			train.text_outside = fields.ext_disp or ""
			train.text_inside = fields.int_disp or ""
			train.line = fields.line or ""
			train.routingcode = fields.rc or ""
			minetest.after(0, advtrains.invalidate_path, train_id)
			return
		--send speed command
		elseif fields.send_speed then
			local current_v,speed_input = train.velocity,tonumber(fields.speed_input)
			if not tonumber(speed_input) then
				minetest.chat_send_player(pname,trans("Speed must be a number"))
				return
			end
			local command
			local acc
			speed_input = tonumber(speed_input)
			if current_v == speed_input then
				minetest.chat_send_player(pname,trans("Speed unchanged"))
				return
			elseif current_v < speed_input then
				command = "S"..speed_input
				acc = "accelerating"
			elseif current_v > speed_input then
				command = "B"..speed_input
				acc = "braking"
			end
			advtrains.atc.train_set_command(train,command,true)
			minetest.chat_send_player(pname,trans("Train "..acc.." to "..speed_input))
			return
		--send atc command
		elseif fields.send_atc then
			if fields.atc_input == "" then
				minetest.chat_send_player(pname,trans("No ATC command to send"))
				return
			end
			advtrains.atc.train_set_command(train,fields.atc_input,true)
			return
		-- send reverse command
		elseif fields.reverse then
			if train.velocity ~= 0 then
				minetest.chat_send_player(pname,trans("Please stop the train before reversing"))
				return
			end
			advtrains.invert_train(train_id)
			advtrains.train_ensure_init(train_id,train)
			-- advtrains.atc.train_reset_command(train)
			minetest.chat_send_player(pname,trans("Train reversed"))
			return
		--door control
		elseif door_scroll.type == "CHG" then
			train.door_open = door_scroll.value-2
			return
		-- ars_disable
		elseif fields.ars_disable then
			if not advtrains.interlocking then
				return
			end
			advtrains.interlocking.ars_set_disable(train,minetest.is_yes(fields.ars_disable))
			return
		-- autocouple
		elseif fields.autocouple == "true" then
			train.autocouple = true
			return
		elseif fields.autocouple == "false" then
			train.autocouple = nil
			return
		-- emergency stop button
		elseif fields.estop then
			advtrains.atc.train_set_command(train,"BB",true)
			minetest.chat_send_player(pname,trans("Emergency Brake applied"))
			return
		end
	end
end)

minetest.register_craftitem(modname..":remote_control",{
	description = trans("Unbound Controller"),
	short_description = trans("Unbound Train Controller"),
	groups = {},
	inventory_image = "advtrains_rc_controller.png",
	wield_image = "advtrains_rc_controller.png",
	stack_max = 1,
	on_use = function(itemstack, user, pointed_thing)
		local pname = user:get_player_name()
		if not pname or pname == "" then
			return
		end
		if not minetest.check_player_privs(pname, {train_admin=true}) then
			minetest.chat_send_player(pname, trans("Insufficient privileges to use this!"))
			return
		end
		
		local meta = itemstack:get_meta()
		local bound_loco = meta:get_string("bound_loco") -- set to nil to enable bind-mode
		if bound_loco == "" then bound_loco = nil end
		
		if not bound_loco then -- start the search for a locomotive
			if pointed_thing.type == "object" then
				local object = pointed_thing.ref:get_luaentity()
				if not object.id then
					return
				end
				local data = advtrains.wagons[object.id]
				if not data then
					minetest.chat_send_player(pname,trans("This isn't even a train."))
					return
				else
					local wagon = advtrains.wagon_prototypes[data.type or data.entity_name]
					if not wagon then
						minetest.chat_send_player(pname,trans("Wagon '@1' couldn't be found.",data.type))
						return
					else
						if wagon.is_locomotive then -- bind to this locomotive
							meta:set_string("bound_loco",object.id)
							meta:set_string("roadnumber",data.roadnumber or "")
							meta:set_string("description",trans("Bound Controller"))
						else
							minetest.chat_send_player(pname,trans("You can only bind the controller to locomotives"))
							return
						end
					end
				end			
			end
		else
			if not advtrains.wagons[bound_loco] then --loco has been removed from the world. set to unbound
				meta:set_string("bound_loco","")
				meta:set_string("roadnumber","")
				meta:set_string("description",trans("Unbound Controller"))
				minetest.chat_send_player(pname,trans("The locomotive has been removed from the world. Controller is unbound"))
				return itemstack
			end
			
			if meta:get("roadnumber") ~= advtrains.wagons[bound_loco].roadnumber then --update roadnumber for item description
				meta:set_string("roadnumber",advtrains.wagons[bound_loco].roadnumber)
			end
		end
		show_formspec(itemstack,pname)
		return itemstack
	end,
})

minetest.register_craft({
	output = modname..":remote_control",
	recipe = {
		{"default:mese_crystal_fragment","default:diamond","default:copper_ingot"},
		{"steel_ingot","advtrains_luaautomation:oppanel","steel_ingot"},
		{"","default:steel_ingot",""},
	}
})